﻿Imports Microsoft.Xna.Framework
Imports Microsoft.Xna.Framework.Graphics

Namespace Global.Runa.Resources.ContentReader.VectorFont

    ''' <summary>Stores the vertices for a string as filled 3D text</summary>
    Public Class FilledText
        Inherits Text

        ''' <summary>Initializes a new filled string mesh</summary>
        ''' <param name="font">Font from which the vertices will be taken</param>
        ''' <param name="text">String of which to build a mesh</param>
        Friend Sub New(font As VectorFont, text As String)
            resizeVertexAndIndexArrays(font, text)
            buildStringMesh(font, text)
        End Sub

        ''' <summary>Builds the combined mesh for the letters in this string</summary>
        ''' <param name="font">Vector font to take the vertex data from</param>
        ''' <param name="text">String of which a mesh is to be built</param>
        Private Sub buildStringMesh(font As VectorFont, text As String)
            Dim position As Vector2 = Vector2.Zero

            Dim baseVertexIndex As Integer = 0
            ' base index in the vertex array
            Dim baseIndexIndex As Integer = 0
            ' base index in the index array
            For characterIndex As Integer = 0 To text.Length - 1
                Dim fontCharacterIndex As Integer

                ' Only add this character to the mesh if there is an actual font character
                ' for this unicode symbol in the font (characters not imported by the user
                ' will be silently skipped -- this is the only sane option imho)
                If font.CharacterMap.TryGetValue(text(characterIndex), fontCharacterIndex) Then
                    Dim character As VectorFontCharacter = font.Characters(fontCharacterIndex)

                    ' Import all of the vertices of this font (we need both the outline vertices
                    ' as well as the mesh supporting vertices)
                    For index As Integer = 0 To character.Vertices.Count - 1
                        Me.Vertices(baseVertexIndex + index) = New VertexPositionNormalTexture(New Vector3(character.Vertices(index) + position, 0.0F), Vector3.Forward, Vector2.Zero)
                    Next

                    ' Now bend the indices to the new location of the vertices in our
                    ' concatenated vertex array
                    For faceIndex As Integer = 0 To character.Faces.Count - 1
                        Me.Indices(baseIndexIndex + faceIndex * 3 + 0) = CShort(character.Faces(faceIndex).FirstVertexIndex + baseVertexIndex)
                        Me.Indices(baseIndexIndex + faceIndex * 3 + 1) = CShort(character.Faces(faceIndex).SecondVertexIndex + baseVertexIndex)
                        Me.Indices(baseIndexIndex + faceIndex * 3 + 2) = CShort(character.Faces(faceIndex).ThirdVertexIndex + baseVertexIndex)
                    Next

                    ' Advance the index pointers
                    baseIndexIndex += character.Faces.Count * 3
                    baseVertexIndex += character.Vertices.Count

                    ' Update the position to the next character

                    position += character.Advancement
                    ' if
                End If
            Next
            ' for
            Me.Width = position.X
            Me.Height = font.LineHeight
            Me.PrimitiveType = PrimitiveType.TriangleList
        End Sub

        ''' <summary>Reserves the required space in the vertex and index arrays</summary>
        ''' <param name="font">Font the vertices for the letters will be taken from</param>
        ''' <param name="text">String of which a mesh will be built</param>
        Private Sub resizeVertexAndIndexArrays(font As VectorFont, text As String)
            Dim vertexCount As Integer = 0
            Dim indexCount As Integer = 0

            ' Count the vertices and indices requires for all characters in the string
            For index As Integer = 0 To text.Length - 1
                Dim fontCharacterIndex As Integer

                ' Try to find the current character in the font's character map. If it isn't
                ' there, we'll ignore it, just like the mesh creation routine does.
                If font.CharacterMap.TryGetValue(text(index), fontCharacterIndex) Then
                    Dim character As VectorFontCharacter = font.Characters(fontCharacterIndex)

                    vertexCount += character.Vertices.Count
                    indexCount += character.Faces.Count * 3
                End If
            Next

            Me.Vertices = New VertexPositionNormalTexture(vertexCount - 1) {}
            Me.Indices = New Short(indexCount - 1) {}
        End Sub

    End Class

End Namespace